package org.sky.quartz;

import org.apache.logging.log4j.Logger;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.sky.sys.entity.SysQuartz;
import org.sky.util.JsonUtils;
import org.sky.util.LogUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author weifx
 * @Title: QuartzManager
 * @ProjectName springboot-platform
 * @Description: TODO{计划任务管理类}
 * @date 2019/3/14 22:39
 * @Version 1.0
 */
@Component
public class QuartzManager {
    private final static Logger log = LogUtils.getLogger(QuartzManager.class);
    @Autowired
    @Qualifier("Scheduler")
    private Scheduler scheduler;
    /**
     * 获取计划中JOB
     * @return
     */
    public List getPlaningJobs() throws SchedulerException{
        List<SysQuartz> jobList = new ArrayList<SysQuartz>();
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
        Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
        for (JobKey jobKey : jobKeys) {
            List<? extends Trigger> triggers = scheduler
                    .getTriggersOfJob(jobKey);
            for (Trigger trigger : triggers) {
                SysQuartz job = new SysQuartz();
                job.setName(jobKey.getName());
                job.setGroupName(jobKey.getGroup());
                job.setNote("触发器:" + trigger.getKey());
                Trigger.TriggerState triggerState = scheduler
                        .getTriggerState(trigger.getKey());
                job.setStatus(triggerState.name());
                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    job.setCronExpression(cronExpression);
                }
                jobList.add(job);
            }
        }
        return jobList;
    }

    /**
     * 获取运行中JOB
     * @return
     */
    public List getRuningJobs() throws SchedulerException{
        List<SysQuartz> jobList = new ArrayList<SysQuartz>();
        List<JobExecutionContext> executingJobs = scheduler
                .getCurrentlyExecutingJobs();
        for(JobExecutionContext executingJob : executingJobs) {
            SysQuartz job = new SysQuartz();
            JobDetail jobDetail = executingJob.getJobDetail();
            JobKey jobKey = jobDetail.getKey();
            Trigger trigger = executingJob.getTrigger();
            job.setName(jobKey.getName());
            job.setName(jobKey.getGroup());
            job.setNote("触发器:" + trigger.getKey());
            Trigger.TriggerState triggerState = scheduler
                    .getTriggerState(trigger.getKey());
            job.setStatus(triggerState.name());
            if (trigger instanceof CronTrigger) {
                CronTrigger cronTrigger = (CronTrigger) trigger;
                String cronExpression = cronTrigger.getCronExpression();
                job.setCronExpression(cronExpression);
            }
            jobList.add(job);
        }
        return jobList;
    }

    /**
     * 暂停任务
     * @param job
     * @throws SchedulerException
     */
    public void pauseJob(SysQuartz job) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(job.getName(), job.getGroupName());
        scheduler.pauseJob(jobKey);
    }

    /**
     * 恢复任务
     * @param job
     * @throws SchedulerException
     */
    public void resumeJob(SysQuartz job) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(job.getName(), job.getGroupName());
        scheduler.resumeJob(jobKey);
    }

    /**
     * 删除任务后，所对应的trigger也将被删除
     * @param job
     * @throws SchedulerException
     */
    public void delJob(SysQuartz job) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(job.getName(), job.getGroupName());
        scheduler.deleteJob(jobKey);
    }

    /**
     * 立即运行一次
     * @param job
     * @throws SchedulerException
     */
    public void triggerJob(SysQuartz job) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(job.getName(), job.getGroupName());
        scheduler.triggerJob(jobKey);
    }

    /**
     * 更新时间
     * @param jobName
     * @param jobGroupName
     * @param cronExpression
     * @throws SchedulerException
     */
    public void updateCronExpression(String jobName,
                                            String jobGroupName, String cronExpression)
            throws SchedulerException {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
        // 获取trigger，即在spring配置文件中定义的 bean id="myTrigger"
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

        // 表达式调度构建器
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                .cronSchedule(cronExpression);

        // 按新的cronExpression表达式重新构建trigger
        trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                .withSchedule(scheduleBuilder).build();

        // 按新的trigger重新设置job执行
        scheduler.rescheduleJob(triggerKey, trigger);
    }

    /**
     * 运行
     * @param job
     * @throws SchedulerException
     * @throws ClassNotFoundException
     */
    public void runJob(SysQuartz job) throws SchedulerException,
            ClassNotFoundException {
        TriggerKey triggerKey = TriggerKey.triggerKey(job.getName(),
                job.getGroupName());
        CronTrigger trigger = null;
        JobDetail jobDetail = JobBuilder
                .newJob((Class<? extends Job>) Class.forName(job.getExeClass()))
                .withIdentity(job.getName(), job.getGroupName()).build();
        jobDetail.getJobDataMap().put("scheduleJob", job);

        // 表达式调度构建器
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                .cronSchedule(job.getCronExpression());

        // 按新的cronExpression表达式构建一个新的trigger
        trigger = TriggerBuilder.newTrigger()
                .withIdentity(job.getName(), job.getGroupName())
                .withSchedule(scheduleBuilder).build();

        scheduler.scheduleJob(jobDetail, trigger);
        if (!scheduler.isShutdown()) {
            scheduler.start();
        }

    }

    /**
     * 获取状态
     * NONE：Trigger已经完成，且不会在执行，或者找不到该触发器，或者Trigger已经被删除
     * NORMAL:正常状态
     * PAUSED：暂停状态
     * COMPLETE：触发器完成，但是任务可能还正在执行中
     * BLOCKED：线程阻塞状态
     * ERROR：出现错误
     * @param job
     * @return
     */
    public String getTriggerState(SysQuartz job){
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(job.getName(),
                    job.getGroupName());
            return scheduler.getTriggerState(triggerKey).name();
        }catch (Exception e){
            log.error("查询计划任务{}状态失败", JsonUtils.obj2json(job));
            return "ERROR";
        }
    }
}
